package com.whale.controllers;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.ui.Model;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;

import com.whale.kernel.domain.HtmlMenu;
import com.whale.kernel.model.pagination.Pagination;
import com.whale.kernel.model.pagination.Step;
import com.whale.kernel.provider.ServletContextProvider;
import com.whale.kernel.service.HtmlMenuService;
import com.whale.kernel.service.HtmlPageService;
import com.whale.kernel.service.UserService;

public abstract class AbstractController {

	private Logger logger = LoggerFactory.getLogger(AbstractController.class);

	protected static Integer MAX_RESULTS_PER_PAGE = 100;
	protected static Integer DEFAULT_RESULTS_PER_PAGE = 3;

	protected HtmlMenuService htmlMenuService;

	protected HtmlPageService htmlPageService;

	protected UserService userService;

	protected MessageSource messages;
	
	protected ServletContextProvider servletContextProvider;

	public void setMessages(MessageSource messages) {
		this.messages = messages;
	}

	public void setHtmlMenuService(HtmlMenuService htmlMenuService) {
		this.htmlMenuService = htmlMenuService;
	}

	public void setHtmlPageService(HtmlPageService htmlPageService) {
		this.htmlPageService = htmlPageService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}
	
	public void setServletContextProvider(
			ServletContextProvider servletContextProvider) {
		this.servletContextProvider = servletContextProvider;
	}

	protected void populateNavigation(Model model, String navigationPath,
			String menuGroupId) {
		// get top level menu list
		List<HtmlMenu> topLevelMenus = htmlMenuService
				.getTopLevelHtmlMenus(menuGroupId);
		model.addAttribute("topLevelMenus", topLevelMenus);
		// get current selected top level menu
		HtmlMenu currentMenu = htmlMenuService.findHtmlMenu(navigationPath);
		model.addAttribute("currentTopLevelMenu", currentMenu);
		// get sub menu list
		List<HtmlMenu> subMenus = htmlMenuService
				.getSubHtmlMenus(navigationPath);
		model.addAttribute("subMenus", subMenus);
	}

	protected void populateSubNavigation(Model model, String navigationPath,
			String subNavigationPath, String menuGroupId) {
		populateNavigation(model, navigationPath, menuGroupId);
		// get current selected sub menu
		HtmlMenu currentMenu = htmlMenuService.findHtmlMenu(subNavigationPath);
		model.addAttribute("currentSubMenu", currentMenu);
	}

	protected void populatePagination(String path, HttpServletRequest request,
			Model model, Step currentStep, long total) {
		int nbPages = (int) Math.ceil((double) total / currentStep.getMax());
		if (nbPages < 2) {
			return;
		}
		int indexPage = (int) Math.ceil((double) currentStep.getOffset()
				/ currentStep.getMax());
		currentStep.setIndex(indexPage + 1);

		Pagination pagination = new Pagination();
		pagination.setCurrentLink(currentStep);
		if (indexPage > 0 && nbPages > 1) {
			pagination.setPrevLink(new Step(currentStep.getMax(), currentStep
					.getOffset() - currentStep.getMax(), 1));
		}
		if (indexPage < (nbPages - 1) && nbPages > 1) {
			pagination.setNextLink(new Step(currentStep.getMax(), currentStep
					.getOffset() + currentStep.getMax(), nbPages));
		}
		List<Step> stepLinks = new ArrayList<Step>();
		for (int i = 0; i < nbPages; i++) {
			stepLinks.add(new Step(currentStep.getMax(), i
					* currentStep.getMax(), i + 1));
		}
		pagination.setStepLinks(stepLinks);
		pagination.setPath(path);
		model.addAttribute("paginationObj", pagination);
	}

	protected Step getCurrentPageStep(HttpServletRequest request) {
		Step step = null;
		try {
			Integer max = ServletRequestUtils.getIntParameter(request, "max");
			Integer offset = ServletRequestUtils.getIntParameter(request,
					"offset");
			if (max == null || offset == null) {
				return new Step(DEFAULT_RESULTS_PER_PAGE, 0);
			}
			if (max.intValue() <= 0) {
				max = Integer.valueOf(1);
			}
			if (max.intValue() > MAX_RESULTS_PER_PAGE) {
				max = Integer.valueOf(MAX_RESULTS_PER_PAGE);
			}

			step = new Step(max, offset);
		} catch (ServletRequestBindingException e) {
			logger.error(e.getMessage(), e);
		}
		return step;
	}
}
